package com.tianyu.inspection.service;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tianyu.inspection.entity.*;
import com.tianyu.inspection.mapper.*;
import com.tianyu.inspection.service.api.IProjectStatisticsService;
import com.tianyu.inspection.entity.*;
import com.tianyu.inspection.mapper.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

/**********************************
 * @Author YSW
 * @Description 数据统计
 * @Date 2021/3/1 - 10:39
 **********************************/

@Service
public class ProjectStatisticsServiceImpl implements IProjectStatisticsService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private PipelineMapper pipelineMapper;

    @Resource
    private FlyTaskMapper flyTaskMapper;

    @Resource
    private DangerMapper dangerMapper;

    @Resource
    private DangerTypeMapper dangerTypeMapper;

    @Resource
    private DangerProcessMapper dangerProcessMapper;

    @Resource
    private ConstructionUnitsMapper constructionUnitsMapper;

    @Resource
    private ConstructionTypeMapper constructionTypeMapper;

    @Resource
    private HighConsequenceAreasMapper highConsequenceAreasMapper;

    @Resource
    private HighConsequenceAreasTypeMapper highConsequenceAreasTypeMapper;

    @Resource
    private PileCardMapper pileCardMapper;

    @Resource
    private PileCardTypeMapper pileCardTypeMapper;

    @Resource
    private GeneralFacilitiesMapper generalFacilitiesMapper;

    @Resource
    private GeneralFacilitiesTypeMapper generalFacilitiesTypeMapper;

    @Resource
    private OrthographicImageMapper orthographicImageMapper;

    @Resource
    private CameraMapper cameraMapper;

    @Resource
    private CameraTypeMapper cameraTypeMapper;

    /**
     * 项目概要统计：
     * 各项目用户总量
     * 各项目管线总量
     * 各项目任务总量
     * 各项目险情总量
     * 各项目文件总量
     * 各项目基础设施总量
     *
     * @return Result
     */
    @Override
    public JSONObject projectSummaryStatistics(Integer projectId) {
        final Integer userCount = Math.toIntExact(userMapper.selectCount(new QueryWrapper<User>().eq("project_id", projectId).eq("state", 0)));
        final Integer dangerCount = Math.toIntExact(dangerMapper.selectCount(new QueryWrapper<Danger>().eq("project_id", projectId).eq("state", 0)));
        final Integer flyTaskCount = Math.toIntExact(flyTaskMapper.selectCount(new QueryWrapper<FlyTask>().eq("project_id", projectId).eq("state", 0)));
        final Integer pipelineCount = Math.toIntExact(pipelineMapper.selectCount(new QueryWrapper<Pipeline>().eq("project_id", projectId).eq("state", 0)));
        final Integer orthographicImageCount = Math.toIntExact(orthographicImageMapper.selectCount(new QueryWrapper<OrthographicImage>().eq("project_id", projectId).eq("state", 0)));
        final Integer pileCardCount = Math.toIntExact(pileCardMapper.selectCount(new QueryWrapper<PileCard>().eq("project_id", projectId).eq("state", 0)));
        final Integer cameraCount = Math.toIntExact(cameraMapper.selectCount(new QueryWrapper<Camera>().eq("project_id", projectId).eq("state", 0)));
        final Integer highConsequenceAreasCount = Math.toIntExact(highConsequenceAreasMapper.selectCount(new QueryWrapper<HighConsequenceAreas>().eq("project_id", projectId).eq("state", 0)));
        final Integer ConstructionUnitsCount = Math.toIntExact(constructionUnitsMapper.selectCount(new QueryWrapper<ConstructionUnits>().eq("project_id", projectId).eq("state", 0)));
        final Integer generalFacilitiesCount = Math.toIntExact(generalFacilitiesMapper.selectCount(new QueryWrapper<GeneralFacilities>().eq("project_id", projectId).eq("state", 0)));
        return new JSONObject()
                .fluentPut("userCount", userCount)
                .fluentPut("dangerCount", dangerCount)
                .fluentPut("flyTaskCount", flyTaskCount)
                .fluentPut("pipelineCount", pipelineCount)
                .fluentPut("orthographicImageCount", orthographicImageCount)
                .fluentPut("pileCardCount", pileCardCount)
                .fluentPut("cameraCount", cameraCount)
                .fluentPut("highConsequenceAreasCount", highConsequenceAreasCount)
                .fluentPut("ConstructionUnitsCount", ConstructionUnitsCount)
                .fluentPut("generalFacilitiesCount", generalFacilitiesCount);
    }

    /**
     * 飞行历史统计
     * type 统计时间跨度类型 1 按年统计 2 按月统计 3 按日统计
     *
     * @return Result
     */
    @Override
    public JSONArray flyTaskStatistics(Integer projectId, Integer type, String startTime, String endTime) {
        String select = "COUNT(*) as count";
        final QueryWrapper<FlyTask> queryWrapper = new QueryWrapper<FlyTask>()
                .eq("state", 0).eq("project_id", projectId);
        if (type != null) {
            String format = getMysqlDateFormat(type);
            String formatPattern = getDateDateFormat(type);
            SimpleDateFormat sdf = new SimpleDateFormat(formatPattern);
            if (startTime != null && endTime != null) {
                String startTimeFormat = sdf.format(new Date(Long.parseLong(startTime)));
                String endTimeFormat = sdf.format(new Date(Long.parseLong(endTime)));
                String date = ",DATE_FORMAT(create_time, " + format + ") as date";
                select += date;
                queryWrapper
                        .between("DATE_FORMAT(create_time, " + format + ")", startTimeFormat, endTimeFormat)
                        .groupBy("date");
                ;
            }
        }
        queryWrapper.select(select);
        final List<Map<String, Object>> maps = flyTaskMapper.selectMaps(queryWrapper);
        return new JSONArray().fluentAddAll(maps);
    }

    private String getDateDateFormat(Integer type) {
        String formatPattern = "yyyy-MM";
        if (type == 4) {
            formatPattern = "yyyy-MM-dd HH:mm:ss";
        } else if (type == 3) {
            formatPattern = "yyyy-MM-dd";
        } else if (type == 2) {
            formatPattern = "yyyy-MM";
        } else if (type == 1) {
            formatPattern = "yyyy";
        }
        return formatPattern;
    }

    private String getMysqlDateFormat(Integer type) {
        String format = "'%Y-%m'";
        if (type == 4) {
            format = "'%Y-%m-%d %H:%i:%S'";
        } else if (type == 3) {
            format = "'%Y-%m-%d'";
        } else if (type == 2) {
            format = "'%Y-%m'";
        } else if (type == 1) {
            format = "'%Y'";
        }
        return format;
    }


    @Override
    public JSONArray dangerStatistics(Integer projectId, Integer type, String startTime, String endTime) {
        String select = "COUNT(*) as count";
        final QueryWrapper<Danger> queryWrapper = new QueryWrapper<Danger>()
                .eq("state", 0).eq("project_id", projectId);
        if (type != null) {
            String format = getMysqlDateFormat(type);
            String formatPattern = getDateDateFormat(type);
            SimpleDateFormat sdf = new SimpleDateFormat(formatPattern);
            if (startTime != null && endTime != null) {
                String startTimeFormat = sdf.format(new Date(Long.parseLong(startTime)));
                String endTimeFormat = sdf.format(new Date(Long.parseLong(endTime)));
                String date = ",DATE_FORMAT(create_time, " + format + ") as date";
                select += date;
                queryWrapper
                        .between("DATE_FORMAT(create_time, " + format + ")", startTimeFormat, endTimeFormat)
                        .groupBy("date");
                ;
            }
        }
        queryWrapper.select(select);
        final List<Map<String, Object>> maps = dangerMapper.selectMaps(queryWrapper);
        return new JSONArray().fluentAddAll(maps);
    }

    /**
     * 险情统计
     *
     * @return Result
     */
    @Override
    public JSONObject dangerDerailsStatistics(Integer projectId, Integer type, String startTime, String endTime) {
        String format = null;
        String startTimeFormat = null;
        String endTimeFormat = null;
        if (startTime != null && endTime != null) {
            format = "'%Y-%m-%d %H:%i:%S'";
            String formatPattern = "yyyy-MM-dd HH:mm:ss";
            SimpleDateFormat sdf = new SimpleDateFormat(formatPattern);
            startTimeFormat = sdf.format(new Date(Long.parseLong(startTime)));
            endTimeFormat = sdf.format(Long.parseLong(endTime));
        }
        final QueryWrapper<Danger> queryWrapper5 = new QueryWrapper<Danger>().eq("project_id", projectId).eq("state", 0);
        if (startTime != null && endTime != null) {
            queryWrapper5.between("DATE_FORMAT(create_time, " + format + ")", startTimeFormat, endTimeFormat);
        }
        Integer total = Math.toIntExact(dangerMapper.selectCount(queryWrapper5));

        // 按类型统计
        final QueryWrapper<Danger> queryWrapper2 = new QueryWrapper<Danger>()
                .select("danger_type_id as dangerTypeId ,COUNT(*) as count")
                .eq("project_id", projectId)
                .eq("state", 0)
                .groupBy("dangerTypeId");
        if (startTime != null && endTime != null) {
            queryWrapper2.between("DATE_FORMAT(create_time, " + format + ")", startTimeFormat, endTimeFormat);
        }
        List<Map<String, Object>> dangerTypeMapList = dangerMapper.selectMaps(queryWrapper2);
        final JSONArray dangerTypeIds = new JSONArray();
        for (Map<String, Object> stringObjectMap : dangerTypeMapList) {
            dangerTypeIds.add(stringObjectMap.get("dangerTypeId"));
        }
        if (dangerTypeIds.size() != 0) {
            final QueryWrapper<DangerType> id = new QueryWrapper<DangerType>().in("id", dangerTypeIds);
            final List<DangerType> dangerTypes = dangerTypeMapper.selectList(id);
            final HashMap<Integer, String> dangerTypeMap = new HashMap<>();
            for (DangerType dangerType : dangerTypes) {
                dangerTypeMap.put(dangerType.getId(), dangerType.getTypeName());
            }
            for (Map<String, Object> map : dangerTypeMapList) {
                map.put("dangerTypeName", dangerTypeMap.get((int) map.get("dangerTypeId")));
            }
        }


        // 按等级统计
        final QueryWrapper<Danger> queryWrapper3 = new QueryWrapper<Danger>()
                .select("danger_level_id as dangerLevelId,COUNT(*) as count")
                .eq("project_id", projectId)
                .eq("state", 0)
                .groupBy("danger_level_id");
        if (startTime != null && endTime != null) {
            queryWrapper3.between("DATE_FORMAT(create_time, " + format + ")", startTimeFormat, endTimeFormat);
        }
        List<Map<String, Object>> dangerLevelMapList = dangerMapper.selectMaps(queryWrapper3);


        // 获取所有险情经纬度集合
        final QueryWrapper<Danger> queryWrapper = new QueryWrapper<Danger>().select("lat,lng").eq("project_id", projectId).eq("state", 0);
        if (startTime != null && endTime != null) {
            queryWrapper.between("DATE_FORMAT(create_time, " + format + ")", startTimeFormat, endTimeFormat);
        }
        List<Danger> dangers = dangerMapper.selectList(queryWrapper);
        final JSONArray dangerLatLngArray = new JSONArray();
        for (Danger danger : dangers) {
            dangerLatLngArray.add(new JSONArray().fluentAdd(danger.getLat()).fluentAdd(danger.getLng()));
        }

        // 按处理人统计
        final QueryWrapper<Danger> queryWrapper1 = new QueryWrapper<Danger>()
                .select("status,COUNT(*) as count")
                .eq("project_id", projectId)
                .eq("state", 0)
                .groupBy("status");
        if (startTime != null && endTime != null) {
            queryWrapper1.between("DATE_FORMAT(create_time, " + format + ")", startTimeFormat, endTimeFormat);
        }
        List<Map<String, Object>> statusMapList = dangerMapper.selectMaps(queryWrapper1);
        List<Map<String, Object>> dealUserMapList = dangerProcessMapper.selectMaps(new QueryWrapper<DangerProcess>()
                .select("inspector_id as inspectorId,COUNT(*) as count")
                .eq("project_id", projectId)
                .eq("state", 0)
                .groupBy("inspector_id")
                .orderByDesc("count"));
        final JSONArray inspectorIds = new JSONArray();
        for (Map<String, Object> stringObjectMap : dealUserMapList) {
            final Object inspectorId = stringObjectMap.get("inspectorId");
            inspectorIds.add(inspectorId);
        }
        if(inspectorIds.size() > 0){
            final QueryWrapper<User> queryWrapper4 = new QueryWrapper<User>()
                    .in("id", inspectorIds)
                    .eq("project_id", projectId)
                    .eq("state", 0);
            final List<User> users = userMapper.selectList(queryWrapper4);
            for (Map<String, Object> stringObjectMap : dealUserMapList) {
                final Optional<User> inspector = users.stream().filter(user -> user.getId().equals(stringObjectMap.get("inspectorId"))).findFirst();
                if (inspector.isPresent()) {
                    stringObjectMap.put("inspectorName", inspector.get().getNickName());
                } else {
                    stringObjectMap.put("inspectorName", "-");
                }
            }
        }



        return new JSONObject()
                .fluentPut("total", total)
                .fluentPut("latLngs", dangerLatLngArray)
                .fluentPut("dangerType", dangerTypeMapList)
                .fluentPut("dangerLevel", dangerLevelMapList)
                .fluentPut("status", statusMapList)
                .fluentPut("dangerDealUser", dealUserMapList);
    }

    /**
     * 基础设施统计
     *
     * @return Result
     */
    @Override
    public JSONObject infrastructureStatistics(Integer projectId) {
        List<Map<String, Object>> highConsequenceAreasTypeMapList = highConsequenceAreasMapper.selectMaps(new QueryWrapper<HighConsequenceAreas>()
                .select("high_consequence_areas_type_id as highConsequenceAreasTypeId,COUNT(*) as count")
                .eq("project_id", projectId)
                .eq("state", 0)
                .groupBy("high_consequence_areas_type_id"));

        List<Map<String, Object>> constructionMapList = constructionUnitsMapper.selectMaps(new QueryWrapper<ConstructionUnits>()
                .select("construction_type_id as constructionTypeId,COUNT(*) as count")
                .eq("project_id", projectId)
                .eq("state", 0)
                .groupBy("construction_type_id"));

        List<Map<String, Object>> pileCardMapList = pileCardMapper.selectMaps(new QueryWrapper<PileCard>()
                .select("pile_card_type_id as pileCardTypeId,COUNT(*) as count")
                .eq("project_id", projectId)
                .eq("state", 0)
                .groupBy("pile_card_type_id"));

        List<Map<String, Object>> generalFacilitiesMapList = generalFacilitiesMapper.selectMaps(new QueryWrapper<GeneralFacilities>()
                .select("general_facilities_type_id as generalFacilitiesTypeId,COUNT(*) as count")
                .eq("project_id", projectId)
                .eq("state", 0)
                .groupBy("general_facilities_type_id"));

        List<Map<String, Object>> cameraMapList = cameraMapper.selectMaps(new QueryWrapper<Camera>()
                .select("camera_type_id as cameraTypeId,COUNT(*) as count")
                .eq("project_id", projectId)
                .eq("state", 0)
                .groupBy("camera_type_id"));


        return new JSONObject().fluentPut("highConsequenceAreas", highConsequenceAreasTypeMapList)
                .fluentPut("constructionUnits", constructionMapList)
                .fluentPut("pileCard", pileCardMapList)
                .fluentPut("generalFacilities", generalFacilitiesMapList)
                .fluentPut("camera", cameraMapList);
    }

    /**
     * 管线统计
     *
     * @param projectId
     * @return Result
     */
    @Override
    public JSONArray pipelineStatistics(Integer projectId, Integer type, String startTime, String endTime) {
        String select = "COUNT(*) as count";
        final QueryWrapper<Pipeline> queryWrapper = new QueryWrapper<Pipeline>()
                .eq("state", 0).eq("project_id", projectId);
        if (type != null) {
            String format = getMysqlDateFormat(type);
            String formatPattern = getDateDateFormat(type);
            SimpleDateFormat sdf = new SimpleDateFormat(formatPattern);
            if (startTime != null && endTime != null) {
                String startTimeFormat = sdf.format(new Date(Long.parseLong(startTime)));
                String endTimeFormat = sdf.format(new Date(Long.parseLong(endTime)));
                String date = ",DATE_FORMAT(create_time, " + format + ") as date";
                select += date;
                queryWrapper
                        .between("DATE_FORMAT(create_time, " + format + ")", startTimeFormat, endTimeFormat)
                        .groupBy("date");
                ;
            }
        }
        queryWrapper.select(select);
        final List<Map<String, Object>> maps = pipelineMapper.selectMaps(queryWrapper);
        return new JSONArray().fluentAddAll(maps);
    }

    /**
     * 正射统计
     *
     * @param projectId
     * @return Result
     */
    @Override
    public JSONArray orthographicImageStatistics(Integer projectId, Integer type, String startTime, String endTime) {
        String select = "COUNT(*) as count";
        final QueryWrapper<OrthographicImage> queryWrapper = new QueryWrapper<OrthographicImage>()
                .eq("state", 0).eq("project_id", projectId);
        if (type != null) {
            String format = getMysqlDateFormat(type);
            String formatPattern = getDateDateFormat(type);
            SimpleDateFormat sdf = new SimpleDateFormat(formatPattern);
            if (startTime != null && endTime != null) {
                String startTimeFormat = sdf.format(new Date(Long.parseLong(startTime)));
                String endTimeFormat = sdf.format(new Date(Long.parseLong(endTime)));
                String date = ",DATE_FORMAT(create_time, " + format + ") as date";
                select += date;
                queryWrapper
                        .between("DATE_FORMAT(create_time, " + format + ")", startTimeFormat, endTimeFormat)
                        .groupBy("date");
                ;
            }
        }
        queryWrapper.select(select);
        final List<Map<String, Object>> maps = orthographicImageMapper.selectMaps(queryWrapper);
        return new JSONArray().fluentAddAll(maps);
    }

    /**
     * 基础设施类型统计
     *
     * @return Result
     */
    @Override
    public JSONObject infrastructureTypeStatistics(Integer projectId) {
        Integer count1 = Math.toIntExact(highConsequenceAreasTypeMapper.selectCount(new QueryWrapper<HighConsequenceAreasType>().eq("state", 0)));
        Integer count2 = Math.toIntExact(constructionTypeMapper.selectCount(new QueryWrapper<ConstructionType>().eq("state", 0)));
        Integer count3 = Math.toIntExact(pileCardTypeMapper.selectCount(new QueryWrapper<PileCardType>().eq("state", 0)));
        Integer count4 = Math.toIntExact(generalFacilitiesTypeMapper.selectCount(new QueryWrapper<GeneralFacilitiesType>().eq("state", 0)));
        Integer count5 = Math.toIntExact(cameraTypeMapper.selectCount(new QueryWrapper<CameraType>().eq("state", 0)));
        return new JSONObject().fluentPut("highConsequenceAreasType", count1)
                .fluentPut("constructionType", count2)
                .fluentPut("pileCardType", count3)
                .fluentPut("generalFacilitiesType", count4)
                .fluentPut("cameraType", count5);
    }
}
